package cc.shacocloud.mirage.restful;

import cc.shacocloud.mirage.restful.exception.ResourceNotFoundException;
import cc.shacocloud.mirage.utils.resource.Resource;
import io.vertx.core.Future;
import io.vertx.core.buffer.Buffer;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.lang.reflect.Method;
import java.util.Objects;

/**
 * 基于 {@link StaticResourceHandlerImpl} 实现的 {@link VertxInvokeHandler}
 *
 * @author 思追(shaco)
 */
public class VertxInvokeStaticResourceHandler extends VertxInvocableHandlerMethod implements VertxInvokeHandler {
    
    private static final Method invokeMethod;
    
    static {
        try {
            invokeMethod = StaticResourceHandler.class.getMethod("findPathResource", RoutingContext.class);
        } catch (NoSuchMethodException e) {
            throw new RuntimeException(e);
        }
    }
    
    private final StaticResourceHandler staticResourceHandler;
    
    public VertxInvokeStaticResourceHandler(StaticResourceHandler staticResourceHandler) {
        super(new HandlerMethod(staticResourceHandler, invokeMethod));
        this.staticResourceHandler = staticResourceHandler;
    }
    
    @Override
    public Future<Object> invokeAndHandleRoutingContext(@NotNull RoutingContext routingContext, Object... providedArgs) {
        return staticResourceHandler.findPathResource(routingContext).map(r -> r);
    }
    
    @Override
    public Future<Buffer> resultHandle(@Nullable Object result, HttpResponse response) {
        if (Objects.isNull(result)) return Future.failedFuture(new ResourceNotFoundException());
        
        if (!(result instanceof Resource)) {
            return Future.failedFuture(new UnsupportedOperationException());
        }
        
        Resource resource = (Resource) result;
        return staticResourceHandler.sendResource(response, resource).map(r -> null);
    }
    
    @Override
    public Object getHandler() {
        return staticResourceHandler;
    }
}
